<template>
	<wt-select 
		ref="select"
		v-model="currentValue"
		:multiple="multiple"
		:query="currentQuery"
		:remote="true"
		:params-data="paramsData"
		@options="optionsLoaded"
		:custom-label="field.customLabel"
		:empty-notice="emptyNotice"
	></wt-select>
</template>
<script>

	/*
	 * 用于在不同model实体之间建立关联的选择器。
	 */

	import Vue from 'vue';
	import ElementUI from 'element-ui';
	import request from '../utils/axios';
	import Select from './wt-select';
	import FormUtils from '../utils/wt-form-utils'
	import Service from '../utils/wt-model-service'

	Vue.use(ElementUI);

	const Success = 'success';
	const Fail = 'fail';
	const Uploading = 'uploading';
	const Ready = 'ready';
	const Added = 'added';
	const Removed = 'removed';

	export default {
		name: 'wt-model-link-selector',
		props: {
			value: {
				type: Array,
				default: null
			},
			multiple: Boolean,
			uploadConfig: {
				type: Object,
				required: true
			},
			deleteConfig: {
				type: Object,
				required: true
			},
			linkedModel: {
				type: Object,
				required: true
			},
			paramsData: {
				type: Object,
				default: null
			},
			parentId: {
				type: [String, Number],
				default: null
			},
			field: {
				type: Object,
				required: true
			}
		},
		data() {
			return {
				currentValue: this.value ? [] : null,	//延迟加载，等待select组件加载完选项再绑定value，否则在没有选项表的时候会显示数字id值（见optionsLoaded)
				items: this.createItems(this.value),
				currentQuery: this.linkedModel.query,
				successCallback: null,
				errorCallback: null,
				startedProcessing: false
			}
		},
		watch: {
			'value'(val, oldValue) {
				if (val === oldValue) return;
				this.reset();
			},
		},
		computed: {
			emptyNotice() {
				return '当前没有' + this.linkedModel.title;
			}
		},
		methods: {
			load() {
				this.$refs.select.load();
			},
			submit(successCallback, errorCallback) {
				this.successCallback = successCallback;
				this.errorCallback = errorCallback;

				this.findNewItems();
				this.findRemovedItems();
				this.upload();
			},
			reset() {
				this.itemsBeforeChange = this.createItems(this.value);
			},
			upload(index = 0) {
				if (index < this.items.length) {
					let item = this.items[index];
					let status = item.status;
					if (status == Success || status == Uploading || status == Fail) {
						// Try next item
						this.upload(index + 1);
						return;
					}
					let config = null;
					if (status == Added) {
						config = this.uploadConfig;
					}
					else if (status == Removed) {
						config = this.deleteConfig;
					} 
					if (config) {
						let data = {};
						if (config.parentIdParam) {
							data[config.parentIdParam] = this.parentId;
						}
						if (config.uploadParam) {
							data[config.uploadParam] = item.value;
						}
						item.status = Uploading;
						let _this = this;
						request(config.url, config.method, data, config.transfer, function(data) {
							item.status = Success;
							_this.upload(index + 1);
							return;
						}, function(error) {
							console.error(error);
							_this.errorCallback();
							_this.successCallback = null;
							_this.errorCallback = null;
							_this.startedProcessing = false;
						})
					}
				}
				else {
					this.successCallback();
					this.successCallback = null;
					this.errorCallback = null;
					this.startedProcessing = false;
				}
			},
			findNewItems() {
				for (let i = 0; i < this.currentValue.length; i ++) {
					let value = this.currentValue[i];
					let existingItem = this.findItemByValue(value);
					
					if (!existingItem) {
						this.items.push({
							value: value,
							status: Added,
						});
					}
				}
			},
			findRemovedItems() {
				for (let i = 0; i < this.items.length; i ++) {
					let item = this.items[i];
					if (item.status == Removed) {
						continue;
					}
					let foundItem = false;
					for (let j = 0; j < this.currentValue.length; j ++) {
						if (this.currentValue[j] == item.value) {
							foundItem = true;
							break;
						}
					}
					if (!foundItem && item.original) {
						item.status = Removed;
					}
				}
			},
			createItems(value) {
				let items = [];
				if (value) {
					let source = FormUtils.parseArray(value);
					for (let i = 0; i < source.length; i ++) {
						let item = source[i];
						items.push({
							value: item,
							status: Success,
							original: true
						});
					}
				}
				return items;
			},
			findItemByValue(value) {
				for (let i = 0; i < this.items.length;i ++) {
					if (this.items[i].value == value) {
						return this.items[i];
					}
				}
				return null;
			},
			optionsLoaded(options) {
				if (options.length > 0 && this.value != null) {
					let _this = this;
					this.$nextTick(() => {
						_this.currentValue = _this.value;
					});
				}
			},
		},
	}

</script>